/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = rtsp_header.c                                      */
/*  NOTE      =                                                    */
/*  DATE      = 2015/07/14 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <frct_comm.h>
#include <ctype.h>

#include "rtsp_comm.h"
#include "rtsp_core.h"

/*******************************************************************************
*  FUNC     :  分析RTSP头
*           :  *p_payload                           (数据内容)
*           :  ui_payload_len                       (数据长度)
*           :  *p_i_is_sip_req                      (是否是SIP请求)
*           :  **pp_req_method                      (SIP请求的方法)
*           :  *req_method                          (SIP请求的方法)
*           :  *p_i_content_length                  (CONTENT的长度)
*  RTN      :  0                                        (FR_SUCC)
*              1                                        (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int rtsp_analyze_header(char *p_payload
                        , unsigned int ui_payload_len
                        , int *p_i_is_req
                        , char **pp_req_method
                        , Rtsp_req_method *req_method
                        , int *p_i_content_length)
{
    char *p_pos = NULL;
    unsigned int ui_firstline_len_left = 0;
    int i_content_len = 0;
    unsigned int ui_fields_len_left = 0;
    char *p_colon_pos = NULL;
    unsigned int ui_line_len = 0;
    char *p_field_value = NULL;
    unsigned int ui_field_value_len = 0;

    if(p_payload == NULL || ui_payload_len == 0)
        goto error;

    //取第一行
    if ((p_pos = strstr(p_payload, APM_RTSP_EOL)) == NULL ||
            (ui_firstline_len_left = p_pos - p_payload) == 0)
        goto error;

    if (strncmp(p_payload, APM_RTSP_VERSION""APM_RTSP_SP, strlen(APM_RTSP_VERSION""APM_RTSP_SP)) == 0) // 有可能是响应
    {
        if (p_i_is_req != NULL)
            *p_i_is_req = FR_NO;

        //判断Status-Line  =  RTSP-Version SP Status-Code SP Reason-Phrase CRLF
        if (ui_firstline_len_left < strlen(APM_RTSP_VERSION""APM_RTSP_SP) + 3 + strlen(APM_RTSP_SP))
            goto error;
        if(strncmp(p_payload, APM_RTSP_VERSION""APM_RTSP_SP, strlen(APM_RTSP_VERSION""APM_RTSP_SP)) != 0)
            goto error;
        p_payload += strlen(APM_RTSP_VERSION""APM_RTSP_SP);

        // Status-Code: 1xx 2xx 3xx 4xx 5xx
        if (p_payload[0] < '1' || p_payload[0] > '5' ||
            p_payload[1] < '0' || p_payload[1] > '9' ||
            p_payload[2] < '0' || p_payload[2] > '9' ||
            p_payload[3] != ' ')
            goto error;

        p_payload = p_pos + strlen(APM_RTSP_EOL);
    }
    else // 有可能是请求
    {
        if (p_i_is_req != NULL)
            *p_i_is_req = FR_YES;

        //判断是否符合 Request-Line  =  Method SP Request-URI SP RTSP-Version CRLF
        //请求方法(Method)判断
        if (strncmp(p_payload, APM_RTSP_METHOD_OPTIONS""APM_RTSP_SP, strlen(APM_RTSP_METHOD_OPTIONS""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_OPTIONS""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_OPTIONS""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_OPTIONS);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_OPTIONS;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_DESCRIBE""APM_RTSP_SP, strlen(APM_RTSP_METHOD_DESCRIBE""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_DESCRIBE""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_DESCRIBE""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_DESCRIBE);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_DESCRIBE;
        }
        else if (strncmp(p_payload, APM_RTSP_METHOD_ANNOUNCE""APM_RTSP_SP, strlen(APM_RTSP_METHOD_ANNOUNCE""APM_RTSP_SP)) == 0 )
        {
            p_payload += strlen(APM_RTSP_METHOD_ANNOUNCE""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_ANNOUNCE""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_ANNOUNCE);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_ANNOUNCE;
        }
        else if (strncmp(p_payload, APM_RTSP_METHOD_SETUP""APM_RTSP_SP, strlen(APM_RTSP_METHOD_SETUP""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_SETUP""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_SETUP""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_SETUP);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_SETUP;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_PLAY""APM_RTSP_SP, strlen(APM_RTSP_METHOD_PLAY""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_PLAY""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_PLAY""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_PLAY);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_PLAY;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_PAUSE""APM_RTSP_SP, strlen(APM_RTSP_METHOD_PAUSE""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_PAUSE""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_PAUSE""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_PAUSE);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_PAUSE;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_TEARDOWN""APM_RTSP_SP, strlen(APM_RTSP_METHOD_TEARDOWN""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_TEARDOWN""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_TEARDOWN""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_TEARDOWN);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_TEARDOWN;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_GET_PARAMETER""APM_RTSP_SP, strlen(APM_RTSP_METHOD_GET_PARAMETER""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_GET_PARAMETER""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_GET_PARAMETER""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_GET_PARAMETER);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_GET_PARAMETER;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_SET_PARAMETER""APM_RTSP_SP, strlen(APM_RTSP_METHOD_SET_PARAMETER""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_SET_PARAMETER""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_SET_PARAMETER""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_SET_PARAMETER);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_SET_PARAMETER;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_REDIRECT""APM_RTSP_SP, strlen(APM_RTSP_METHOD_REDIRECT""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_REDIRECT""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_REDIRECT""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_REDIRECT);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_REDIRECT;
        }
        else if(strncmp(p_payload, APM_RTSP_METHOD_RECORD""APM_RTSP_SP, strlen(APM_RTSP_METHOD_RECORD""APM_RTSP_SP)) == 0)
        {
            p_payload += strlen(APM_RTSP_METHOD_RECORD""APM_RTSP_SP);
            ui_firstline_len_left -= strlen(APM_RTSP_METHOD_RECORD""APM_RTSP_SP);
            if (pp_req_method != NULL)
                *pp_req_method = frstrdup(APM_RTSP_METHOD_RECORD);
            if (req_method != NULL)
                *req_method = RTSP_METHOD_TYPE_RECORD;
        }
        else
            goto error;

        //取第2个space
        p_pos = (char *) memchr(p_payload, ' ', ui_firstline_len_left);
        if(!p_pos)
            goto error;

        ui_firstline_len_left -= p_pos - p_payload + 1;
        p_payload = p_pos + 1;
        //RTSP-Version格式判定(RTSP/1.0)
        if(ui_firstline_len_left != strlen(APM_RTSP_VERSION) && strncmp(p_payload, APM_RTSP_VERSION, strlen(APM_RTSP_VERSION)) != 0)
            goto error;

        p_payload += strlen(APM_RTSP_VERSION""APM_RTSP_EOL);
    }

    if (p_i_content_length != NULL)
    {
        if ((p_pos = strstr(p_payload, APM_RTSP_EOH)) == NULL ||
            (ui_fields_len_left = p_pos - p_payload + strlen(APM_RTSP_EOL)) == 0)
            goto error;
        while (ui_fields_len_left > 0)
        {
            if ((p_pos = strstr(p_payload, APM_RTSP_EOL)) == NULL ||
                (ui_fields_len_left = p_pos - p_payload + strlen(APM_RTSP_EOL)) == 0)
                goto error;
            ui_line_len = p_pos - p_payload;

            if (p_payload[0] == ' ' || p_payload[0] == '\t')
            {
                p_payload = p_pos + strlen(APM_RTSP_EOL);
                continue;
            }
            if (strncasecmp(p_payload, "Content-length", strlen("Content-length")) == 0)
            {
                if((p_colon_pos = (char *) memchr(p_payload, ':', ui_line_len)) == NULL)
                    goto error;
                ui_field_value_len = p_pos - p_colon_pos + 1;
                if ((p_field_value = (char *) frmalloc(sizeof(char) * (ui_field_value_len + 1))) == NULL)
                {
                    RTSP_MALLOCK_ERR;
                    goto error;
                }
                memcpy(p_field_value, p_colon_pos + 1, ui_field_value_len);
                p_field_value[ui_field_value_len] = '\0';
                frtrim(p_field_value);
                i_content_len = atoi(p_field_value);
                RTSP_PRINT_WARN("Content-length:[%d]\n", i_content_len);
                rtsp_free((void **) &p_field_value);
                break;
            }
            p_payload = p_pos + strlen(APM_RTSP_EOL);
        }
        *p_i_content_length = i_content_len;
    }

    return FR_SUCC;
error:
    rtsp_free((void **) &p_field_value);
    return FR_FAIL;
}
